package org.dallasrowing.model.dao.sqlmap;

import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.dallasrowing.logbook.event.ChangeHandler;
import org.dallasrowing.logbook.event.ChangeHandlerImpl;
import org.dallasrowing.logbook.event.ChangeListener;
import org.dallasrowing.model.LogBookEntry;
import org.dallasrowing.model.Rower;
import org.dallasrowing.model.dao.DAOException;
import org.dallasrowing.model.dao.LogBookDAO;

import com.ibatis.sqlmap.client.SqlMapClient;

public class SqlMapLogBookDao implements LogBookDAO {

	private static final String ROWER_ID = "rowerId";
	private static final String ENTRY_OPEN_DATE = "entryOpenDate";
	private static final String LOGBOOK_CREATE = "LogBook.insertLogBookEntry";
	private static final String LOGBOOK_ENTRYPARTICIPANTS_CREATE = "LogBook.insertEntryParticipant";

	private static final String LOGBOOK_SELECTALL = "LogBook.selectAllLogBookEntries";
	private static final String LOGBOOK_SELECTBYDATE = "LogBook.selectByDate";
	private static final String LOGBOOK_CLOSEENTRY = "LogBook.closeEntry";
	private static final String LOGBOOK_SELECTOPEN = "LogBook.selectByOpen";
	private static final String LOGBOOK_COUNTALL = "LogBook.countAll";
	
	private SqlMapClient sqlMap;
	private ChangeHandler changeHandler;
	public SqlMapLogBookDao(SqlMapClient sqlMap)
	{
		this.sqlMap = sqlMap;
		this.changeHandler = new ChangeHandlerImpl();
	}
	
	public void create(LogBookEntry entry) throws DAOException {
		try {
			sqlMap.startBatch();
			sqlMap.insert( LOGBOOK_CREATE, entry);
			for ( Rower rower : entry.getRowers() )
			{
				HashMap<String, Object> map = new HashMap<String, Object>();
				map.put( ENTRY_OPEN_DATE, entry.getEntryOpenDate() );
				map.put( ROWER_ID, rower.getId() );
				sqlMap.insert(LOGBOOK_ENTRYPARTICIPANTS_CREATE, map );
			}
			sqlMap.executeBatch();
			
			changeHandler.notifyChanged();
		} catch (SQLException e) {
			throw new DAOException( e );
		}
	}

	@SuppressWarnings( "unchecked" )
	public List<LogBookEntry> getEntriesSortByDate(int offset, int count) throws DAOException {
		try {
			return sqlMap.queryForList(  LOGBOOK_SELECTALL, new Limit(offset,count)  );
		} catch (SQLException e) {
			throw new DAOException( e );
		}
	}

	public int update(LogBookEntry entry) throws DAOException {
		try {
			int retVal = sqlMap.update( LOGBOOK_CLOSEENTRY, entry );
			
			if (retVal != 1)
				throw new DAOException( "updated rows != 1", null);
			
			changeHandler.notifyChanged();
			
			return retVal;
		} catch (SQLException e) {
			throw new DAOException( e );
		}
	}

	public LogBookEntry findLogEntryByDate(Date entryOpenDate) throws DAOException {
		try {
			return (LogBookEntry) sqlMap.queryForObject( LOGBOOK_SELECTBYDATE, entryOpenDate );
		} catch (SQLException e) {
			throw new DAOException( e );
		}
	}

	@SuppressWarnings("unchecked") 
	public List<LogBookEntry>  findOpenEntriesSortByDate() throws DAOException {
		try {
			return sqlMap.queryForList(  LOGBOOK_SELECTOPEN );
		} catch (SQLException e) {
			throw new DAOException( e );
		}
	}

	public int getEntriesCount() throws DAOException {
		try {
			return (Integer) sqlMap.queryForObject( LOGBOOK_COUNTALL );
		} catch (SQLException e) {
			throw new DAOException( e );
		}
	}

	public class Limit
	{
		private int offset;
		private int count;
		
		public Limit(int offset, int count) {
			this.offset = offset;
			this.count = count;
		}
		
		public int getOffset() {
			return offset;
		}
		public int getCount() {
			return count;
		}
	}

	public void registerChangeListener(ChangeListener listener) {
		changeHandler.register(listener);
	}


}
